package implementation;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.HashMap;

import udp.UdpClient;
import udp.UdpServer;
import udp.message.CreateAccountMessage;
import udp.message.GetNonReturnersMessage;
import udp.message.LibraryMessage;
import udp.message.ReserveBookInterMessage;
import udp.message.ReserveBookMessage;
import udp.message.SetDurationMessage;
import udp.message.UdpMessage;



public class SequencerImpl extends UdpServer{

	private UdpClient concordia1;
	private UdpClient concordia2;
	private UdpClient concordia3;
	private UdpClient concordia4;
	private UdpClient mcgill1;
	private UdpClient mcgill2;
	private UdpClient mcgill3;
	private UdpClient mcgill4;
	private UdpClient uqam1;
	private UdpClient uqam2;
	private UdpClient uqam3;
	private UdpClient uqam4;

	
	private int sequence;
	public SequencerImpl(String id, int port) {
		super(id, port);
		this.sequence = 0;
		initializedClient();
	}

	@Override
	public synchronized void receiveMessage(UdpMessage message) {
		System.out.println("Received a message");
		incrementSequenceNumber();
		message.setSequenceNumber(sequence);
		multicast(message);

	}

	public synchronized void incrementSequenceNumber(){
		this.sequence++;
		System.out.println("Incrementing sequence number to: " + this.sequence);
	}

	public void multicast(UdpMessage message){
		System.out.println("Trying to Multicast");
		
		if (message instanceof LibraryMessage){
			System.out.println("message is library message");
			
			if( message instanceof CreateAccountMessage){
				
				CreateAccountMessage createmessage = (CreateAccountMessage) message;
				if (createmessage.getEdu().equals("CONCORDIA")){
					System.out.println("Sequencer Impl lvl: Sending create account to all concordia");
					sendToConcordia(message);
					System.out.println("Sequencer Impl lvl: DONE Sending create account to all concordia");
				}
				else if (createmessage.getEdu().equals("MCGILL")){
					System.out.println("Sequencer Impl lvl: Sending create account to all mcgill");
					sendToMcgill(message);
					System.out.println("Sequencer Impl lvl: Done Sending create account to all mcgill");
					
				}
				else if (createmessage.getEdu().equals("UQAM")){
					System.out.println("Sequencer Impl lvl: Sending create account to all uqam");
					sendToUqam(message);
					System.out.println("Sequencer Impl lvl: Done Sending create account to all uqam");
				}
			}
			else if (message instanceof ReserveBookMessage){
				ReserveBookMessage reservermessage = (ReserveBookMessage) message;
				if (reservermessage.getEi().equals("CONCORDIA")){
					System.out.println("Sequencer Impl lvl: Sending reserve book to all concordia");
					sendToConcordia(message);
					System.out.println("Sequencer Impl lvl: Sending reserve book to all concordia");
				}
				else if (reservermessage.getEi().equals("MCGILL")){
					System.out.println("Sequencer Impl lvl: Sending reserve book to all mcgill");
					sendToMcgill(message);
					System.out.println("Sequencer Impl lvl: DONE Sending reserve book to all mcgill");
					
				}
				else if (reservermessage.getEi().equals("UQAM")){
					System.out.println("Sequencer Impl lvl: Sending reserve book to all uqam");
					sendToUqam(message);
					System.out.println("Sequencer Impl lvl: DONE Sending reserve book to all uqam");
				}
			}
			else if (message instanceof ReserveBookInterMessage){
				ReserveBookInterMessage reserveintermessage = (ReserveBookInterMessage) message;
				if (reserveintermessage.getEi().equals("CONCORDIA")){
					System.out.println("Sequencer Impl lvl: Sending reserve book inter to all concordia");
					sendToConcordia(message);
					System.out.println("Sequencer Impl lvl: DONE Sending reserve book inter to all concordia");
				}
				else if (reserveintermessage.getEi().equals("MCGILL")){
					System.out.println("Sequencer Impl lvl: Sending reserve book inter to all mcgill");
					sendToMcgill(message);
					System.out.println("Sequencer Impl lvl: DONE Sending reserve book inter to all mcgill");
					
				}
				else if (reserveintermessage.getEi().equals("UQAM")){
					System.out.println("Sequencer Impl lvl: Sending reserve book inter to all uqam");
					sendToUqam(message);
					System.out.println("Sequencer Impl lvl: DONE Sending reserve book inter to all uqam");
				}
				
			}
			else if (message instanceof SetDurationMessage){
				SetDurationMessage durationmessage = (SetDurationMessage) message;
				if (durationmessage.getEi().equals("CONCORDIA")){
					System.out.println("Sequencer Impl lvl: Sending duration to all concordia");
					sendToConcordia(message);
					System.out.println("Sequencer Impl lvl: DONE Sending duration to all concordia");
				}
				else if (durationmessage.getEi().equals("MCGILL")){
					System.out.println("Sequencer Impl lvl: Sending duration to all mcgill");
					sendToMcgill(message);
					System.out.println("Sequencer Impl lvl: DONE Sending duration to all mcgill");
					
				}
				else if (durationmessage.getEi().equals("UQAM")){
					System.out.println("Sequencer Impl lvl: Sending duration to all uqam");
					sendToUqam(message);
					System.out.println("Sequencer Impl lvl: DONE Sending duration to all uqam");
				}
				
			}
			else if (message instanceof GetNonReturnersMessage){
				GetNonReturnersMessage getNonmessage = (GetNonReturnersMessage) message;
				if (getNonmessage.getEi().equals("CONCORDIA")){
					System.out.println("Sequencer Impl lvl: Sending Get non returners to all concordia");
					sendToConcordia(message);
					System.out.println("Sequencer Impl lvl: DONE Sending Get non returners to all concordia");
				}
				else if (getNonmessage.getEi().equals("MCGILL")){
					System.out.println("Sequencer Impl lvl: Sending Get non returners to all mcgill");
					sendToMcgill(message);
					System.out.println("Sequencer Impl lvl: DONE Sending Get non returners to all mcgill");
					
				}
				else if (getNonmessage.getEi().equals("UQAM")){
					System.out.println("Sequencer Impl lvl: Sending Get non returners to all uqam");
					sendToUqam(message);
					System.out.println("Sequencer Impl lvl: DONE Sending Get non returners to all uqam");
				}
				
			}
		}
	}
	
	public void initializedClient(){
		System.out.println("Sequencer Initializing.");
		
		try {
			concordia1 = new  UdpClient("nurse",4100);
			concordia2 = new  UdpClient("ochoa",4100);
			concordia3 = new  UdpClient("nernst",4100);
			concordia4 = new  UdpClient("neruda",4100);
			mcgill1 = new  UdpClient("nurse",4200);
			mcgill2 = new  UdpClient("ochoa",4200);
			mcgill3 = new  UdpClient("nernst",4200);
			mcgill4 = new  UdpClient("neruda",4200);
			uqam1 = new  UdpClient("nurse",4300);
			uqam2 = new  UdpClient("ochoa",4300);
			uqam3 = new  UdpClient("nernst",4300);
			uqam4 = new  UdpClient("neruda",4300);
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void sendToConcordia(UdpMessage message){
		message.setSrcPort(4100);
		message.setSrcHost("nurse");
		concordia1.send(message);
		message.setSrcHost("ochoa");
		concordia2.send(message);
		message.setSrcHost("nernst");
		concordia3.send(message);
		message.setSrcHost("neruda");
		concordia4.send(message);
	}
	public void sendToMcgill(UdpMessage message){
		message.setSrcPort(4200);
		message.setSrcHost("nurse");
		mcgill1.send(message);
		message.setSrcHost("ochoa");
		mcgill2.send(message);
		message.setSrcHost("nernst");
		mcgill3.send(message);
		message.setSrcHost("neruda");
		mcgill4.send(message);
	}
	public void sendToUqam(UdpMessage message){
		message.setSrcPort(4300);
		message.setSrcHost("nurse");
		uqam1.send(message);
		message.setSrcHost("ochoa");
		uqam2.send(message);
		message.setSrcHost("nernst");
		uqam3.send(message);
		message.setSrcHost("neruda");
		uqam4.send(message);
	}
	
}
